package controllers

import (
	"encoding/base64"
	"fmt"
	"git.oschina.net/dddailing/deepserver/models"
	"github.com/astaxie/beego"
	"github.com/astaxie/beego/orm"
	"github.com/astaxie/beego/utils"
	"github.com/dailing/levlog"
	"io/ioutil"
	"math/rand"
	"os"
)

var FinishedChannel = make(chan *models.Jsontype, 0)

var DipServer = models.NewImageServer().RegisterCallback(func(jfile *models.Jsontype) {
	// this is the task_finish_callback function for digital image processing server
	if !jfile.HasKey("mata_data") {
		levlog.Error("Json Not complete")
		return
	}
	levlog.Trace("Task ", jfile.ReadObject("mata_data").ReadIntWithDefault("task_id", -1),
		" Method ", jfile.ReadObject("mata_data").ReadString("image_type"),
		" finished",
	)
	FinishedChannel <- jfile
}, func(j *models.Jsontype) bool {
	return true
})

func generateFileName() string {
	filename := ""
	for {
		filename = fmt.Sprint(rand.Int(), ".jpg")
		if utils.FileExists("data/" + filename) {
			continue
		}
		break
	}
	return filename
}

func FinishedTaskHandlerStart() error {
	o := orm.NewOrm()
	levlog.Trace("finished task handler started")
	go func() {
		for {
			jfile := <-FinishedChannel
			record := models.DiagoniseDetail{
				RecordID: jfile.ReadObject("mata_data").
					ReadIntWithDefault("task_id", -1),
			}
			if record.RecordID <= 0 {
				levlog.Error("No record id found")
				continue
			}
			rrec := models.DiagnoseRecord{
				ID: record.RecordID,
			}
			o = orm.NewOrm()
			levlog.E(o.Read(&rrec))
			fileContent, err := base64.StdEncoding.DecodeString(
				jfile.ReadObject("files").ReadString("output_image"))
			levlog.E(err)
			t := jfile.ReadObject("mata_data").ReadString("image_type")
			imageName := fmt.Sprint(record.RecordID,
				"_", t, ".jpg",
			)
			err = ioutil.WriteFile("data/" + imageName, fileContent, os.FileMode(0664))
			levlog.E(err)
			levlog.Trace("handle ", t, " type")
			record.PatientID = rrec.PatientID
			record.Type = t
			record.WhichEye = jfile.ReadObject("mata_data").ReadString("which_eye")
			record.Area = jfile.ReadObject("quantifier_result").ReadFloat("area")
			record.Count = jfile.ReadObject("quantifier_result").ReadInt("count")
			record.Percentage = jfile.ReadObject("quantifier_result").ReadFloat("percentage")
			record.Desp = jfile.ReadObject("quantifier_result").ReadString("desp")
			record.Image = imageName
			_, err = o.Insert(&record)
			levlog.E(err)
		}
	}()
	return nil
}

type NewDiagnoseController struct {
	beego.Controller
}

func (c *NewDiagnoseController) Post() {
	//json := models.NewJsonFile()

	// read and parse body
	infoBody := c.GetString("info")
	levlog.Trace(infoBody)
	infoJson := models.ParseJson(infoBody)

	// make record in db
	// make patient information record
	o := orm.NewOrm()
	patientRecord := models.PatientRecord{
		PatientName:     infoJson.ReadStringWithDefault("name", "NOT GIVEN"),
		PatientID:       infoJson.ReadStringWithDefault("id", "NOT GIVEN"),
		PatientAge:      infoJson.ReadIntWithDefault("age", -1),
		PatientGender:   infoJson.ReadStringWithDefault("gender", "NOT GIVEN"),
		PatientEyesight: infoJson.ReadStringWithDefault("eyesight", "Not Given"),
	}
	patientID, err := o.Insert(&patientRecord)
	levlog.Trace("Patient ID is :", patientID)
	levlog.E(err)

	handleFile := func(filename string, whicheye string) {

		// make diagnose record
		diagnoseRecord := models.DiagnoseRecord{
			PatientID:     int(patientID),
			ImageOriginal: GetOriginalImageName(int(patientID), whicheye),
		}
		diagnoseID, err := o.Insert(&diagnoseRecord)
		levlog.E(err)

		// save file to local storage
		file, head, err := c.GetFile(filename)
		levlog.E(err)
		levlog.Trace("read file :", head.Filename)
		fileContent, err := ioutil.ReadAll(file)
		levlog.E(err)
		levlog.Trace("Read file length : ", len(fileContent))
		originalImageName := diagnoseRecord.ImageOriginal
		err = ioutil.WriteFile("data/" + originalImageName, fileContent, os.FileMode(0664))
		levlog.E(err)

		// Set up processing task
		mataData := models.NewJsonFile()
		mataData.Set("task_id", diagnoseID)
		mataData.Set("which_eye", whicheye)
		files := models.NewJsonFile()
		files.Set("original_image", base64.StdEncoding.EncodeToString(fileContent))
		overallJson := models.NewJsonFile()
		overallJson.Set("mata_data", mataData)
		overallJson.Set("files", files)
		overallJson.ReadObject("mata_data").Set("image_type", "ex")
		DipServer.AddDiagnose(overallJson.Clone())
		overallJson.ReadObject("mata_data").Set("image_type", "ha")
		DipServer.AddDiagnose(overallJson.Clone())
		overallJson.ReadObject("mata_data").Set("image_type", "ve")
		DipServer.AddDiagnose(overallJson.Clone())
		overallJson.ReadObject("mata_data").Set("image_type", "ma")
		DipServer.AddDiagnose(overallJson.Clone())
	}
	handleFile("img_left", "left")
	handleFile("img_right", "right")
	c.Data["json"] = patientRecord
	c.ServeJSON()
}

func GetOriginalImageName(id int, whicheye string) string {
	return fmt.Sprint(id, "_", whicheye, "_og", ".jpg")
}
